#include <stdio.h>
#include <signal.h>
#include <malloc.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h> 
#include <unistd.h>

#include "core.h"
#include "file_operation.h"

static int file_lock_set(FILE *stream, int type);

/**
 * @brief   将数据文件中的数据读入链表中
 */
void read_from_file(struct account_data* core_head)
{
    if (!core_head) {
        DEBUG("PARAM ERROR!\n");
        return;
    }
     
    char name[6];
    char code[6];
	
    FILE* save_file;
    struct account_data *scan_list, *temp, *need_free;
    
    save_file = fopen("../.././lib/data.txt","a+");
    file_lock_set(save_file, F_RDLCK);
    
    core_head->next = (struct account_data *)malloc(sizeof(struct account_data));
    need_free = core_head->next;
    scan_list = core_head->next;

    temp = (struct account_data *)malloc(sizeof(struct account_data));
    temp->next = NULL;
    
    /*字符不能直接读入链表，所以先将其读入数组中*/
    fscanf(save_file,"%s%s%d", name, code, &temp->grace);
    strcpy(temp->name, name);
    strcpy(temp->code, code);
	
    while(feof(save_file) == 0) {
		scan_list->next = (struct account_data *)malloc(sizeof(struct account_data));
		scan_list = scan_list->next;
		scan_list->next=NULL;
	
        /*将temp中的数据复制到scan_list_1中，然后将scan_list_1连入链表*/
		strcpy(scan_list->name, temp->name);
		strcpy(scan_list->code, temp->code);
		scan_list->grace = temp->grace;
		
		fscanf(save_file,"%s%s%d", name, code, &temp->grace);
		strcpy(temp->name, name);
		strcpy(temp->code, code);
    }
    
    file_lock_set(save_file, F_UNLCK);

    /*将core_head直接指向第一个节点，然后将创建的头指针的节点以及temp创建的节点free*/
    core_head->next = core_head->next->next;
    free(temp);
    free(need_free);
    fclose(save_file);
}

/**
 *@brief        将链表中的数据写入文件中
 */
void write_to_file(struct account_data* core_head)
{
    if (!core_head) {
        DEBUG("PARAM ERROR!\n");
        return;
    }
    
    struct account_data* scan_file;
    FILE* save_file;

    save_file = fopen("../.././lib/data.txt", "w");
    file_lock_set(save_file, F_WRLCK);
    /*将scan_file指向头指针，从头到尾依次将每个节点的数据写入文件*/
    scan_file = core_head->next;
    while (scan_file != NULL) {
		fprintf(save_file,"%s\t%s\t%d\n", scan_file->name, scan_file->code, scan_file->grace);
		scan_file = scan_file->next;
    }
    file_lock_set(save_file, F_UNLCK);
    fclose(save_file);
}

/**
 *@brief        文件锁
 */
int file_lock_set(FILE *stream, int type)
{
    int fd;
    struct flock lock;

    lock.l_type = type;
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;
    lock.l_pid = -1;

    fd = fileno(stream);

    fcntl(fd,F_GETLK,&lock);

    if (lock.l_type != F_UNLCK) {
		if (lock.l_type == F_RDLCK)  
	    	DEBUG("Read lock already set by %d\n",lock.l_pid);

		if (lock.l_type == F_WRLCK) 
	    	DEBUG("Write lock already set by %d\n",lock.l_pid);					
    }

    lock.l_type = type;
    lock.l_pid = getpid();

    if ((fcntl(fd,F_SETLKW,&lock)) < 0) {
		DEBUG("Lock failed : type = %d\n",lock.l_type);
		return -1;
    }

    switch (lock.l_type) {
	case F_RDLCK:
		    DEBUG("Read lock set by %d\n", getpid());
		    break;

	case F_WRLCK:
		   	DEBUG("write lock set by %d\n", getpid());
		    break;

	case F_UNLCK:
		    DEBUG("Release lock by %d\n", getpid());
		    break;

	default:
		break;
	}

	return 1;
}
	
    
